package za.org.foobar.famon.util;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 *
 */
public class ValueGetter {
    private static final Log log = LogFactory.getLog(ValueGetter.class);

    private String value;
    private String getter;

    public ValueGetter(String value, String getter) {
        setValue(value);
        setGetter(getter);
    }

    public void setValue(String value) {
        this.value = Util.emptyAsNull(value);
    }

    public void setGetter(String getter) {
        this.getter = Util.emptyAsNull(getter);
    }

    public String getValue() {
        if (value != null) {
            if (getter != null) {
                log.warn("Value (" + value + ") is set as well as its getter (" + getter + ") which will be ignored");
            }
            return value;
        } else if (!Util.isEmpty(getter)) {
            return getGetterValue(getter);
        }
        return null;
    }

    /*
    * The class name is the users preference which is either in the "class.method" format or just "class" and
    * the methodName parameter will be used as the default value.
    */
    public static String getGetterValue(String classMethodName) {
        int pos = classMethodName.lastIndexOf('.');
        if (pos < 0) {
            log.error("The value \"" + classMethodName + "\" is not a fully qualified method name");
            return null;
        }
        String className = classMethodName.substring(0,pos);
        String methodName = classMethodName.substring(pos+1);
        log.info("Getting value from class \"" + className + "\" and static method \'" + methodName + "\"");

        Class c;
        try {
            c = Class.forName(className);
        } catch (ClassNotFoundException e) {
            log.error("Class \"" + className + "\" not found");
            return null;
        }
        Method m;
        try {
            m = c.getDeclaredMethod(methodName);
        } catch (NoSuchMethodException e) {
            log.error("Class \"" + className + "\" has no such method \"" + methodName + "\"");
            return null;
        }
        try {
            Object o = m.invoke(null);
            if (o == null) {
                return null;
            }
            return o.toString();
        } catch (IllegalAccessException e) {
            log.error("The method \"" + classMethodName + "\" could not be called: " + e.getMessage());
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            log.error("The method \"" + classMethodName + "\" could not be called: " + e.getMessage(), e);
            Throwable cause = e.getCause();
            if (cause != null) {
                log.error("Cause called: " + cause.getMessage(), cause);
            }
        } catch (NullPointerException e) {
            log.error("The method \"" + classMethodName + "\" is not static.");
        }

        return null;
    }
}
